import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class QueueDemo {

    private Queue queue;
    private int max=16;
    private ReentrantLock lock=new ReentrantLock();
    private Condition notEmpty=lock.newCondition();
    private Condition notFull=lock.newCondition();

    public QueueDemo(int size){
        this.max=size;
        queue=new LinkedList();
    }

    public void put(Object o) throws InterruptedException{
        lock.lock();
        try {
            while (queue.size()==max){
                notFull.await();
            }
            queue.add(o);
            notEmpty.signalAll();
        }finally {
            lock.unlock();
        }

    }

    public Object take() throws InterruptedException{
        lock.lock();
        try {
            while (queue.size()==0){
                notEmpty.await();
            }
            Object item=queue.remove();
            notFull.signalAll();
            return item;
        }finally {
            lock.unlock();
        }

    }

    public static void main(String[] args) {
        QueueDemo queueDemo=new QueueDemo(6);
        Runnable producer=()->{
            while (true) {
                try {
                    queueDemo.put("abc");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable comsumer=()->{
            while (true){
                try {
                    Object take = queueDemo.take();
                    System.out.println(take);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        new Thread(producer).start();

        new Thread(comsumer).start();
    }
}
